#include "get_args.h"
#include <stdio.h>
#include <errno.h> 
#include <sys/io.h> 
#include <string.h>

int file_exist(char filename[]);					/* 判断文件是否存在 */
void generate_fileName(char file_name[], int file_len,  int flag);	/* 生成新的文件名 */
void print_log(int flag, char file_name[], char temp_name[], int size);	/* 打印日志 */
long  getHex(char* hex, unsigned long initial);					/* 将十进制整数转换为 16 进制数据 */
void encrypt(FILE *file_src, FILE *file_des, char file_buf[], int key, char line_text[]);	/* 加密 */
void decrypt(FILE *file_src, FILE *file_des, char file_buf[], int key);	/* 解密 */


int main(int argc, char* argv[]){

	int enc, key, index, fileName_len, file_size;
	char file_name[100], temp_name[100], file_buf[1], key_str[256];
	int *enc_ptr=&enc, *key_ptr=&key;	
	FILE *file_src, *file_des;
	enc=key=index=fileName_len=file_size=0;
	
	while(process_args(argc, argv, enc_ptr, key_ptr, file_name)){

		if(file_exist(file_name)!=0){
			continue;
		}
		/* 将 key 转换为字符串 */	
		sprintf(key_str, "%d", key);
	
		/* 获取文件名长度 */
		fileName_len = strlen(file_name); 
	
		strcpy(temp_name, file_name);
		/* 生成加密 or 解密后的文件名 */
		generate_fileName(file_name, fileName_len, enc);
		
		file_src = fopen(temp_name, "rb");
		file_des = fopen(file_name,"wb");

		while(!feof(file_src)){
			/* 一次读取一个字节 */
			fread(file_buf, 1 , 1, file_src);
		
	
			if(!feof(file_src)){
				/* 判断是加密还是解密 */
				if(enc == 1){

               	 			char line_text[200];
					encrypt(file_src,file_des,file_buf, key, line_text);
				}else{
					decrypt(file_src, file_des, file_buf, key);
				}			
				index++;
			} 
		}
		fclose(file_src);
		fclose(file_des);

		/* 打印日志 */ 
		print_log(enc, file_name, temp_name, index);		
		break;	
	}
	exit(0);
}


/*
 * 判断文件是否存在
 * */
int file_exist(char* filename){
	if(access(filename, 0)!=0){
		printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
		printf("param error\n file is not exist\n");
		printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
		return 1;
	}
	return 0;
}

/*
 * 生成新的文件名
 * */
void generate_fileName(char file_name[], int file_len,  int flag){
	/* 判断是加密还是解密 */
	if(flag == 1){
		file_name[file_len] = '.';
		file_name[file_len + 1] = 'e';
		file_name[file_len + 2] = 'n';
		file_name[file_len + 3] = 'c';
		file_name[file_len + 4] = '\0';
	}
 	if(flag == 0){
		file_name[file_len - 4] = '\0';	
	}	
}
/*
 * 打印日志
 * */
void print_log(int flag, char file_name[], char temp_name[],  int size){
	if(flag == 1){
		printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
		printf("encrypted %d characters in %s\n", size, temp_name);
		printf("encrypted file is %s\n", file_name);
		printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
	}else if(flag == 0){
		printf("-------------------------------------------------------------------\n");
		printf("decrypted %d characters in %s\n", size, temp_name);
		printf("decrypted file is %s\n", file_name);
		printf("-------------------------------------------------------------------\n");
	}
}


/*
 *将十进制转换为 16 进制
 * */
long getHex(char* hex, unsigned long  initial){
	char *nptr;

        memset(hex, 0, sizeof(hex));
        sprintf(hex, "%lx", initial);
	return strtol(hex, &nptr,16);
}


/*
 * 加密
 * 	加密思路如下：首先每次读取一个字节的数据，也就是一个字符，然后将字符的 ASCII 码转化为 16 进制，
 * 	每个字符的 16 进制分别与 十六进制的 key 异或，每行异或后的结果在组合到一起组成一个 16 进制数，然后以 10 进制写入文件
 * */
void encrypt(FILE *file_src, FILE *file_des, char file_buf[], int key, char line_text[]){

		unsigned long temp;
                char hex[20];
                char temp_line[100];
                /* char res_line[100]="0x";*/
		static int count = 0;
		
                if(file_buf[0]!='\n'){
			count = 0;
			temp = getHex(hex,file_buf[0]);
			unsigned long key_hex = getHex(hex, key);
			unsigned long res_hex = temp ^ key_hex;	
                        sprintf(temp_line, "%02x", res_hex);
                        strcat(line_text, temp_line);
                }else{
			count++;	/* 如果连续出现两次以上的 file_buf[0]!='\n'，说明存在空行 */
                        /*strcat(res_line ,line_text);*/
                      	if(count == 1){
				unsigned long res = strtol(line_text,NULL, 16);
                        	fprintf(file_des,"%ld",res);
			}
                        fputc('\n',file_des);
			memset(line_text, 0, sizeof(line_text));
                }
}


/*
 * 解密
 * 	解密这边比加密麻烦一点，解密的思路就是首先读取一行数据，此时数据为十进制。
 * 	然后将一行的十进制数据转换为十六进制，然后拆分，分别与 16 进制的 key 异或，
 * 	将异或完毕后的数字转换成十进制，也就是字符的 ASCII 码，
 * 	最终得到字符，将字符一个个写进文件。
 * */
void decrypt(FILE *file_src, FILE *file_des, char file_buf[], int key){

	char hex[50];
	char hex_pair[2];
	char hex_str[100];
	char res_hex_str[2];
	int i;
	static char line_text[200];
	static int index = 0;
	static int count = 0;
	if(file_buf[0]!='\n'){
		line_text[index] = file_buf[0];
		index++;
		count = 0;
	}else{
		count++;	/* 如果连续出现两次以上的 file_buf[0]!='\n'，说明存在空行 */
		if(count == 1){
		unsigned long dec_num = strtol(line_text, NULL, 10);	
		unsigned long hex_num = getHex(hex, dec_num);
		sprintf(hex_str, "%02x", hex_num);	/* 将当前行的十六进制数据转换成字符串 */
		for(i = 0; i < strlen(hex_str); i++){
			if(i%2==0){
				hex_pair[0] = hex_str[i];
			}else{
				hex_pair[1] = hex_str[i];	
				unsigned long hex_num_pair = strtol(hex_pair, NULL, 16);
				unsigned long key_hex = getHex(hex, key);
				unsigned long res_hex_num = hex_num_pair ^ key_hex;
				sprintf(res_hex_str,"%02x", res_hex_num);
				unsigned int res = strtol(res_hex_str, NULL, 16);
				fputc(res,file_des);

			}

		}}
		
		fputc('\n',file_des);
		index = 0;
		memset(hex_pair, 0, sizeof(hex_pair));
		memset(res_hex_str, 0, sizeof(res_hex_str));
		memset(hex_str, 0, sizeof(hex_str));
		memset(line_text, 0, sizeof(line_text));
	}
}
